#include "command.h"

//命令表
char command_table[7][20] = {"cd", "ls", "pwd", "puts", "gets", "rm", "mkdir_my"};
int command_num = 7;

//do_command的设定，为了提供一个通一的接口com_prase
int do_command(char* command, char* answer_client, int fd)
{
    //去掉client发过来字符串末尾的换行符；----客户端已经对发送来的命令做了正确性解析！
    //    int len = strlen(command);
    //    len--;  //不计算换行符长度
    //    command[len] = '\0'; //字符串结束符
    command_t com_prase;
    prase(command, &com_prase);

    execute(&com_prase, answer_client, fd);
    return 0;
}

int prase(char* command, command_t* pcom)
{
    //分离命令 和 [文件名或目录名]
    //存放到command结构体中
    char* p = command;
    int i = 0, j = 0;
    while (*p) {
        if (*p != ' ') {

            pcom->com[i] = *p;
            i++;
            p++;
        }
        else 
            break;
    }
    pcom->com[i] = '\0';
    //    printf("com: %s\n", pcom->com);

    p++;
    while(*p) {
        pcom->name[j] = *p;
        j++;
        p++;
    }
    pcom->name[j] = '\0';
    return 0;

}

int search(char* com)
{
    for (int i = 0; i < command_num; i++) {
        if (!strcmp(com, command_table[i])) {
            return i;
        }
    }
    return -1;
}

//4、执行客户端的命令
void execute(command_t* pcom, char* answer_client, int fd)
{  
    int num = search(pcom->com); 
    printf("command in execute %s %s\n", pcom->com, pcom->name);
    switch (num) {
    case 0:
        cd(pcom->name, answer_client);
        break;
    case 1:
        cmd_ls(answer_client);
        break;
    case 2:
        pwd(answer_client);
        break;
    case 3:
        if (!recv_file(fd)) {
            strcpy(answer_client, "upload success, beautiful"); 
        }  //接收文件成功，才打印语句
        break;
    case 5:
        rm(pcom->name, answer_client);
        break;
    case 6:
        mkdir_my(pcom->name, answer_client);
        break;
    default:
        puts("server: illegal command!");
        //若command为空
        strcpy(answer_client, "illegal command!"); 
    }
}


void cd(char* name, char* answer_client)
{
    int retVal = chdir(name);
    //发生错误，不采用ERROR_CHECK，那样会exit终止子进程
    //采用把出错信息写入answer_client，回传给客户端
    ERROR_CHECK_M(retVal, -1, "cd", answer_client);
    char* cwd = getcwd(answer_client, BUFFERSIZE);
    ERROR_CHECK(cwd, NULL,"getcwd in child");
}

//实现ls命令
void cmd_ls(char *answer){
    char pwdnow[256];
    getcwd(pwdnow,sizeof(pwdnow));

    int ret;
    DIR *dir = opendir(pwdnow);
    ERROR_CHECK(dir,(DIR*)-1,"opendir");

    struct dirent *p = NULL;
    struct stat buf;
    int answer_size = 0;
    while((p=readdir(dir)))
    {
        if(strcmp(p->d_name,".") && strcmp(p->d_name,".."))
        {
            ret=stat(p->d_name,&buf);
            ERROR_CHECK(ret,-1,"stat");

            char *ret_from_ctime = ctime(&buf.st_mtime);
            ret_from_ctime[16] = '\0';

            ret=sprintf(answer+answer_size,"%s %ld %s %s %10ld %s %s\n"
                        ,trans_file_access_form(&buf)
                        ,buf.st_nlink
                        ,getpwuid(buf.st_uid)->pw_name
                        ,getgrgid(buf.st_gid)->gr_name
                        ,buf.st_size
                        ,ret_from_ctime+4
                        ,p->d_name);
            answer_size += ret;
        }
    }
    closedir(dir);
    return;
}

//转换文件权限格式
char *trans_file_access_form(void* file_stat){
    struct stat *buf = (struct stat *)file_stat;
    int decimal_form = buf->st_mode & S_IFMT;
    char *ret = (char *)calloc(11, sizeof(char));
    char types[] = "xwrpcdb-ls";
    ret[0] = types[(decimal_form >>= 12) / 2 + 3];
    decimal_form = buf->st_mode;
    int  pos = 9;
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 3; ++j,decimal_form >>= 1)
        {
            if (decimal_form & 1)
            {
                ret[pos--] = types[j];
            }
            else
            {
                ret[pos--] = types[7];
            }
        }
    }
    return ret;
}

void pwd(char* answer_client)
{
    char* cwd = getcwd(answer_client, BUFFERSIZE);
    ERROR_CHECK_M(cwd, NULL, "pwd", answer_client);
}

void rm(char* name, char* answer_client) 
{
    int retVal = remove(name);
    ERROR_CHECK_M(retVal, -1, "rm", answer_client);
    strcpy(answer_client, "OK");
}

void mkdir_my(char* name, char* answer_client) 
{
    int retVal = mkdir(name, 0777);
    ERROR_CHECK_M(retVal, -1, "mkdir", answer_client);
    strcpy(answer_client, "OK");
}
